package com.sinosoft.ebusiness.aspect;

import com.sinosoft.ebusiness.annotation.CacheAnnotation;
import com.sinosoft.ebusiness.util.RedisConfig;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;


@Aspect
@Component
public class CacheAspect {

    Logger logger = LoggerFactory.getLogger(CacheAspect.class);

    @Pointcut(value="execution(* com.sinosoft.ebusiness.spring.*.*Impl.*.*(..))")
    public void pointCut1(){}
    @Pointcut(value="execution(* com.sinosoft.ebusiness.spring.*.*Mapper.*.*(..))")
    public void pointCut2(){}

    @Around("pointCut1() || pointCut2()")
    public Object catTransactionProcess(ProceedingJoinPoint pjp) throws Throwable {
        Class tarClazz = pjp.getTarget().getClass();
        String className = tarClazz.getName();
        String methodName = pjp.getSignature().getName();
        MethodSignature joinPointObject = (MethodSignature) pjp.getSignature();
        Method method = joinPointObject.getMethod();
        Object[] ages = pjp.getArgs();

        CacheAnnotation cacheAnnotation = method.getAnnotation(CacheAnnotation.class);

        if(null != cacheAnnotation){
            String key  = code(className,methodName,ages);
            if(null != RedisConfig.get(key.getBytes())){
                return RedisConfig.get(key.getBytes());
            }else{
                Object value = pjp.proceed();
                RedisConfig.set(key, (int) cacheAnnotation.unit().toSeconds(cacheAnnotation.timeout()),value);//
                logger.info("the timeOut :{},the key : {}" , cacheAnnotation.unit().toSeconds(cacheAnnotation.timeout()),key);
                return  value;
            }
        }else{
            return pjp.proceed();
        }
    }

    // 通过className.methodName.args生成唯一标识key
    private String code(String className,String methodName,Object[] args){
        StringBuilder builder = new StringBuilder(className+"."+methodName+".");
        for (Object a : args){
            builder.append(a.hashCode()+".");
        }
        return builder.toString();
    }


}